AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include( 'shared.lua' )

function ENT:Initialize()
	self.Entity:SetModel( self.LaserModel )
	self.Entity:PhysicsInit( SOLID_VPHYSICS ) 	
	self.Entity:SetMoveType( MOVETYPE_VPHYSICS )
	self.Entity:SetSolid( SOLID_VPHYSICS ) 
	self.Entity:SetUseType(SIMPLE_USE)  
	RD.RegisterNonStorageDevice(self)
	
	local phys = self.Entity:GetPhysicsObject()
	if (phys:IsValid()) then
		--phys:Wake()
		--phys:EnableGravity(true)
		--phys:EnableDrag(true)
		--phys:EnableCollisions(true)
		--phys:EnableMotion(true)
	end
	
	self.Entity:SetColor( 0, 100, 255, 255 )
	
	--RD.AddResource(self.Entity,"energy", 0)
	
	--RD.AddResource(self, "Blue Ice", 0)
	--RD.AddResource(self, "Clear Ice", 0)
	--RD.AddResource(self, "Glacial Mass", 0)
	--RD.AddResource(self, "White Glaze", 0)
	--RD.AddResource(self, "Dark Glitter", 0)
	--RD.AddResource(self, "Glare Crust", 0)
	--RD.AddResource(self, "Gelidus", 0)
	--RD.AddResource(self, "Krystallos", 0)
	
	self.Inputs = Wire_CreateInputs( self.Entity, { "Activate" } ) 
	self.Outputs = Wire_CreateOutputs( self.Entity, { "Active", "Mineral Amount", "Cycle %" } )
	
	self:SetNWBool("mining", false)
	
	self.nextcycle = CurTime()
	self.nextpull = CurTime()
	self.pulls = 0
	self.InputActive = false
	self.percent = 0
			
end

function ENT:SpawnFunction( ply, tr )

if ( !tr.Hit ) then return end
	
	local SpawnPos = tr.HitPos + tr.HitNormal * 100
	
	local ent = ents.Create( "ice_mining_laser_base" )
		ent:SetPos( SpawnPos )
		ent:Spawn()
		ent:Activate()
		ent.Owner = ply
	return ent
end

function ENT:DoRes()

	local energy = RD.GetResourceAmount(self, "energy")
	local energyneed = self.LaserConsume/self.LaserCycle
	
	if (energy >= energyneed) then	
		self.energytofire = true
		RD.ConsumeResource(self, "energy", energyneed)		
	 	return true		
	else
		self.energytofire = false
		return false
	end 

end

function ENT:Mine()

	if (self.pulls == 0) then		
	
		local ent = self:FindRoid()
		self.roidtomine = ent
		--Msg("Rocks Locked \n")
	
		if not ent then	--No asteroids found
			--Msg("No rocks in range \n")
			self:SetNWBool("mining", false)
			self:SetNWEntity("roid", nil)
			self.nextcycle = CurTime()
			self.nextpull = CurTime()
			self.pulls = 0
			self.nextpull = CurTime() + 1
			Wire_TriggerOutput(self.Entity,"Active",0)
			Wire_TriggerOutput(self.Entity,"Mineral Amount",0)			
			return false
		end
		
		self:SetNWBool("mining", true)
		self:SetNWEntity("roid", ent:EntIndex())
		self.mining = true
		 		
		self.nextcycle = CurTime() + self.LaserCycle 		
	end
	
	local ent = self.roidtomine 
		
	if not ent:IsValid() then	--Did it die while we were mining it?
			--Msg("Asteroid Died :( \n")
			self:SetNWBool("mining", false)
			self:SetNWEntity("roid", nil)
			self.nextcycle = CurTime()
			self.nextpull = CurTime()
			self.pulls = 0
			self.nextpull = CurTime() + 1
			Wire_TriggerOutput(self.Entity,"Active",0)
			Wire_TriggerOutput(self.Entity,"Mineral Amount",0)	
			return false
	end
	--local range = (ent:GetPos() - self:GetPos()):Length()
	local range = (ent:NearestPoint(self:GetPos()) - self:GetPos()):Length()
	if range > self.LaserRange  then	--Did it go out of mining range?
			--Msg("Asteroid out of range "..tostring(range).."\n")
			self:SetNWBool("mining", false)
			self:SetNWEntity("roid", nil)
			self.nextcycle = CurTime()
			self.nextpull = CurTime()
			self:ConsumeOre(ent, false, self.pulls)	
			self.pulls = 0
			self.nextpull = CurTime() + 1
			Wire_TriggerOutput(self.Entity,"Active",0)
			Wire_TriggerOutput(self.Entity,"Mineral Amount",0)
			return false
	end
	self:DoRes()	
		
	if self.energytofire == true then
		self.nextpull = CurTime() + 1	
		self:CalcOre(ent)  		
	else
		--Msg("Ran out of energy "..tostring(self.LaserConsume/self.LaserCycle).."\n")
		self:SetNWBool("mining", false)
		self:SetNWEntity("roid", nil)
		self.nextcycle = CurTime()
		self.nextpull = CurTime()
		self:ConsumeOre(ent, false, self.pulls)	
		self.pulls = 0
		self.nextpull = CurTime() + 1
		Wire_TriggerOutput(self.Entity,"Active",0)
		Wire_TriggerOutput(self.Entity,"Mineral Amount",0)
		return false
	end		  	
end

--Some Ore volumes could be so large that a full cycle is needed to pull just 1 unit, should the cycle break to soon, you would lose this unit
function ENT:CalcOre(ent) --Figures out how much ore to comsume once a cycle is ended or broken

	self.pulls = self.pulls + 1
	----Msg("Pulls: "..tostring(self.pulls).." \n")
	
	----Msg("Percent: "..tostring(self.percent).."% \n")
	
	
	local toextract = (((self.LaserExtract/self.LaserCycle)*self.pulls) / ent.MineralVol)
	
	if toextract > ent.MineralAmount then
		--Msg("Cycyle cut short due to not enough Ore left in roid")
		self:ConsumeOre(ent, true,self.pulls)
		self.pulls = 0
		return
	end 
	
	if self.pulls >= self.LaserCycle then
		self:ConsumeOre(ent, false,self.pulls)
		self.pulls = 0
		Wire_TriggerOutput(self.Entity,"Active",0)
		Wire_TriggerOutput(self.Entity,"Mineral Amount",0)
	else
	 	Wire_TriggerOutput(self.Entity,"Active",1)
		Wire_TriggerOutput(self.Entity,"Mineral Amount",math.floor(ent.MineralAmount))
	end		
end

function ENT:ConsumeOre(ent, takeall, pulls) --Comsumes the Ore

	if takeall then
		--Msg("C Took ALl: " ..tostring(math.floor(ent.MineralAmount)).. " Ore \n")
		ent.MineralAmount = ent.MineralAmount - ent.MineralAmount
		RD.SupplyResource(self, ent.MineralName, math.floor(ent.MineralAmount))
		self.pulls = 0
		return
	else
		local toextract = math.floor((((self.LaserExtract/self.LaserCycle)*self.pulls) / ent.MineralVol))
		----Msg("CPulls"..tostring(self.pulls).." \n")
		--Msg("C Pulled FULL: " ..tostring(toextract).. " Ore \n")
		
		ent.MineralAmount = ent.MineralAmount - toextract
		RD.SupplyResource(self, ent.MineralName, toextract)
		self.pulls = 0 
	end
	if self.InputActive == false then
		self:SetNWBool("mining", false)
		self:SetNWEntity("roid", nil) 		
	end
end 

function ENT:FindRoid()

	local find = ents.FindInSphere(self:GetPos(), self.LaserRange)
	local dist = {}
	local roids = {}
	
	for _,i in pairs(find) do
		if string.find(i:GetClass(), "iceroid") then 		
			local range = (i:NearestPoint(self:GetPos()) - self:GetPos()):Length()
			roids[range] = i
			table.insert(dist, range)					
		end	
	end 
	
	table.sort(dist)  --Sort ranges from lowest to highest
	
	for _,d in pairs(dist) do  --This should take the first value (lowest range) and get the entity it belongs to off the roids table
		return roids[d]	
	end 	
end

function ENT:OnRemove()
	Dev_Unlink_All(self.Entity)
	Wire_Remove(self.Entity)	
end

function ENT:Think()
	self.BaseClass.Think(self)

    self.percent = math.Round((self.pulls/self.LaserCycle)*100)
	self:SetOverlayText(self.PrintName.."\n".."Cycle: "..self.percent.."%")
	
	Wire_TriggerOutput(self.Entity,"Cycle %",self.percent) 	 	
	 
	if self.InputActive and self.nextpull < CurTime() then
		self:Mine()
	elseif self.pulls < self.LaserCycle and self.pulls > 0 then
		if self.nextpull < CurTime() then
			self:Mine()
		end
	end
			
end

function ENT:TriggerInput(iname, value)
	if (iname == "Activate") then
		if value == 1 then
			self.InputActive = true	
			self:Mine()		
		else
			self.InputActive = false			
		end
	end
end

function ENT:PreEntityCopy()
	RD.BuildDupeInfo(self.Entity)
	--build the DupeInfo table and save it as an entity mod
	local DupeInfo = self:BuildDupeInfo()
	if(DupeInfo) then
		duplicator.StoreEntityModifier(self.Entity,"WireDupeInfo",DupeInfo)
	end
end

function ENT:PostEntityPaste(Player,Ent,CreatedEntities)
	RD.ApplyDupeInfo(Ent, CreatedEntities)
	--apply the DupeInfo
	if(Ent.EntityMods and Ent.EntityMods.WireDupeInfo) then
		self.Owner = Player	
		Ent:ApplyDupeInfo(Player, Ent, Ent.EntityMods.WireDupeInfo, function(id) return CreatedEntities[id] end)
	end
end


